package com.sz.biz.logistics.ord.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.sz.biz.common.constants.CommCodes;
import com.sz.biz.common.constants.LanguageCode;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.logistics.billing.dto.QuotationCalcResult;
import com.sz.biz.logistics.billing.service.QuotationCalcService;
import com.sz.biz.logistics.constants.ErrorCodes;
import com.sz.biz.logistics.core.entity.Service;
import com.sz.biz.logistics.core.service.ProductServiceRelService;
import com.sz.biz.logistics.core.service.ServiceService;
import com.sz.biz.logistics.ord.constants.OrderTrackingConstants;
import com.sz.biz.logistics.ord.dto.*;
import com.sz.biz.logistics.ord.entity.*;
import com.sz.biz.logistics.ord.enums.OrdOperationLogEnum;
import com.sz.biz.logistics.ord.enums.TrackMessageToServiceEnum;
import com.sz.biz.logistics.ord.service.*;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.exception.CommonErrorCodes;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.*;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.service.SysDictService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.text.MessageFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Function: 物流跟踪信息<br>
 * Author: hpeng.wang. <br>
 * Date: 2017-03-31 13:53:00.
 */
@org.springframework.stereotype.Service("ordOrderTrackingService")
public class OrdOrderTrackingServiceImpl extends AbstractService implements OrdOrderTrackingService {
    @Autowired
    private OrdOrderService orderService;
    @Autowired
    private OrdServiceOrderService serviceOrderService;
    @Autowired
    private OrdTrackingMessageService trackingMessageService;
    @Autowired
    private OrdSubOrderService subOrderService;
    @Autowired
    private OrdOrderStatusCodeService statusCodeService;
    @Autowired
    private SysDictService dictService;
    @Autowired
    private OrdOrderStatusCodeService orderStatusCodeService;
    @Autowired
    private OrdTrackingMessageService ordTrackingMessageService;
    @Autowired
    private ProductServiceRelService productServiceRelService;
    @Autowired
    private OrdOrderServiceAssignService orderServiceAssignService;
    @Autowired
    private ServiceService serviceService;
    @Autowired
    private QuotationCalcService calcService;


    @Autowired
    private BizOperationLogService operationLogService;

    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.ord.entity.OrdOrderTrackingMapper";
    }

    @Override
    public void save(OrdOrderTracking entry) {
        if (!ObjectUtils.isEmpty(entry)) {
            this.batchSave(Arrays.asList(entry));
        }
    }

    /**
     * 保存服务商返回的物流跟踪信息,
     * 1.服务商返回的是每一个子单的物流信息,要处理是否修改子订单的状态，从而决定是否修改主订单的状态
     * 2.如果当前服务-供应商的工作已经完成，判断是否需要下新的服务订单--生成新的tracking信息
     *
     * @param entry
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int saveAfterTracking(OrdOrderTracking entry) {


        return entry.getId();
    }

    @Override
    public void batchSave(List<OrdOrderTracking> list) {
        if (!CollectionUtils.isEmpty(list)) {
            dao.batchInsert(getSqlName("insert"), list);
            //保存操作日志
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("ADD_ORDER_TRACKING", list);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_TRACKING, UserActions.ADD, "添加物流的跟踪信息", dataBackup);
        }
    }

    @Override
    public void delete(Integer id) {
        if (!ObjectUtils.isEmpty(id)) {
            this.batchDelete(Arrays.asList(id));
        }
    }

    @Override
    public void batchDelete(List<Integer> ids) {
        dao.batchUpdate(getSqlName("deleteByPrimaryKey"), ids);
        //保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_ORDER_TRACKING", ids);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_TRACKING, UserActions.DELETE, "删除物流的跟踪信息", dataBackup);
    }

    @Override
    public void update(OrdOrderTracking entry) {
        if (!ObjectUtils.isEmpty(entry)) {
            this.batchUpdate(Arrays.asList(entry));
        }
    }

    @Override
    public void batchUpdate(List<OrdOrderTracking> list) {
        if (!CollectionUtils.isEmpty(list)) {
            dao.batchUpdate(getSqlName("updateById"), list);
            //保存操作日志
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("UPDATE_ORDER_TRACKING", list);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_TRACKING, UserActions.UPDATE, "修改物流的跟踪信息", dataBackup);
        }
    }


    @Override
    public OrdOrderTracking findById(Integer id) {
        ParamData pd = new ParamData();
        pd.put("id", id);
        OrdOrderTracking entry = (OrdOrderTracking) dao.findForObject(getSqlName("findById"), pd);
        return entry;
    }

    @Override
    public List<OrdOrderTracking> findByIds(List<Integer> ids) {
        if (ids == null || ids.size() <= 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY);
        }
        ParamData pd = new ParamData();
        pd.put("ids", ids);
        List<OrdOrderTracking> list = dao.findForList(getSqlName("findByIds"), pd, OrdOrderTracking.class);
        return list;
    }

    @Override
    public QResultDto findByParam(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        pd.put("language", PrincipalUtils.getLocalLanguage());
        List<Map> list = dao.findForList(getSqlName("findByParamListPage"), pd, Map.class);
        return new QResultDto(list, pd.getPagination());
    }

    @Override
    public List<OrdOrderTracking> findByWaybillNo(String waybillNo, String code, String serviceUid, int status) {
        ParamData pd = new ParamData();
        pd.put("waybillNo", waybillNo);
        pd.put("code", code);
        pd.put("serviceUid", serviceUid);
        pd.put("status", status);
        List<OrdOrderTracking> list = dao.findForList(getSqlName("findByWaybillNo"), pd, OrdOrderTracking.class);
        return list;
    }

    @Override
    public List<OrdOrderTracking> findByWaybillNo(String waybillNo, String code, int status) {
        return this.findByWaybillNo(waybillNo, code, null, status);
    }

    @Override
    public List<OrdOrderTracking> findByWaybillNo(String waybillNo, String code) {
        return this.findByWaybillNo(waybillNo, code, 0);
    }

    @Override
    public List<OrdOrderTracking> findByWaybillNo(String waybillNo) {
        List<OrdOrderTracking> ordOrderTrackingList = this.findByWaybillNo(waybillNo, null, 0);
        return ordOrderTrackingList;
    }

    @Override
    public List<OrdOrderTracking> findBySubOrderNos(List<String> subOrderNos) {
        List<OrdOrderTracking> orderTrackList = Lists.newArrayList();
        if (!ObjectUtils.isEmpty(subOrderNos)) {
            ParamData pd = new ParamData();
            pd.put("subOrderNos", subOrderNos);
            orderTrackList = dao.findForList(getSqlName("findBySubOrderNos"), pd, OrdOrderTracking.class);
        }
        return orderTrackList;
    }

    @Override
    public List<OrdOrderTracking> findByWaybillNos(List<String> waybillNos) {
        List<OrdOrderTracking> orderTrackList = Lists.newArrayList();
        if (!ObjectUtils.isEmpty(waybillNos)) {
            ParamData pd = new ParamData();
            pd.put("waybillNos", waybillNos);
            orderTrackList = dao.findForList(getSqlName("findListByWaybillNos"), pd, OrdOrderTracking.class);
        }
        return orderTrackList;
    }


    @Override
    public Map<String, List<OrdOrderTrackingShowDto>> findByWaybillNo(List<Integer> rankList, String waybillNo) {
        if (!StringUtils.hasLength(waybillNo)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "参数异常！");
        }
        Map<String, List<OrdOrderTrackingShowDto>> trackingMap = null;
        Map<String, Map<String, List<OrdOrderTrackingShowDto>>> trackingShowDtoMap = this.findByWaybillNo(rankList, Arrays.asList(waybillNo));
        if (!ObjectUtils.isEmpty(trackingShowDtoMap)) {
            trackingMap = trackingShowDtoMap.get(waybillNo);
        }

        return trackingMap;
    }


    @Override
    public Map<String, Map<String, List<OrdOrderTrackingShowDto>>> findByWaybillNo(List<Integer> rankList, List<String> waybillNos) {
        if (CollectionUtils.isEmpty(waybillNos)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "参数异常！");
        }

        List<String> orderNos = orderService.findOrderNosByWaybillNos(waybillNos);
        if (CollectionUtils.isEmpty(orderNos)) {
            return null;
        }

        ParamData pd = new ParamData();
        pd.put("ranks", rankList);
        pd.put("orderNos", orderNos);
        pd.put("language", PrincipalUtils.getLocalLanguage());//获取当前的语言
        List<Map> trackingMap = dao.findForList(getSqlName("findByOrderNos"), pd, Map.class);
        Map<String, Map<String, List<OrdOrderTrackingShowDto>>> orderTrackingMapMap = new HashMap<>();

        if (!CollectionUtils.isEmpty(trackingMap)) {
            for (Map<String, Object> trackings : trackingMap) {
                //填充数据
                OrdOrderTrackingShowDto showDto = new OrdOrderTrackingShowDto();
                String waybillNo = (String) trackings.get("waybillNo");
                String subOrderNo = (String) trackings.get("subOrderNo");
                String trackMessage = (String) trackings.get("trackMessage");
                Date messageTime = (Date) trackings.get("messageTime");
                String messageTemplate = (String) trackings.get("messageTemplate");
                String code = (String) trackings.get("code");
                String trackContext = this.getTrackingString(messageTemplate, trackMessage);
                showDto.setTrackMessage(trackContext);
                showDto.setMessageTime(messageTime);
                showDto.setCode(code);

                if (orderTrackingMapMap.get(waybillNo) == null) {
                    Map<String, List<OrdOrderTrackingShowDto>> orderTrackingMap1 = new HashMap<>();
                    orderTrackingMapMap.put(waybillNo, orderTrackingMap1);
                }
                Map<String, List<OrdOrderTrackingShowDto>> orderTrackingMap = orderTrackingMapMap.get(waybillNo);

                //设置到map中
                if (orderTrackingMap.get(subOrderNo) == null) {
                    List<OrdOrderTrackingShowDto> shoDtoList = new ArrayList<>();
                    orderTrackingMap.put(subOrderNo, shoDtoList);
                }
                List<OrdOrderTrackingShowDto> ordOrderTrackingShowDtoList = orderTrackingMap.get(subOrderNo);
                //因为信息可能重复，所以去掉时间在后面的数据，把时间在前面的记录添加进去，因为是倒序排列，所以这样显示
                if (ordOrderTrackingShowDtoList.contains(showDto)) {
                    ordOrderTrackingShowDtoList.remove(showDto);
                }
                orderTrackingMap.get(subOrderNo).add(showDto);
            }
        }

        //把orderTrackingMapMap 的按照请求的waybillNos排序， map的key是set的所以是无序的，这里用LinkedHashMap 来保证顺序
        LinkedHashMap<String, Map<String, List<OrdOrderTrackingShowDto>>> resultMap = new LinkedHashMap<>();
        for (String billNo : waybillNos) {
            if (orderTrackingMapMap.containsKey(billNo)) {
                resultMap.put(billNo, orderTrackingMapMap.get(billNo));
            }
        }
        return resultMap;
    }


    @Override
    public String getTrackingString(String messageTemplate, String trackMessage) {
        if (StringUtils.isEmpty(trackMessage) && StringUtils.hasLength(messageTemplate)) {
            return messageTemplate;
        }
        String[] trackMessageArray = trackMessage.split("\\|");
        messageTemplate = MessageFormat.format(messageTemplate, trackMessageArray);
        return messageTemplate;
    }


    /**
     * 根据code 和trackmessage得到替换后的结果
     *
     * @param code
     * @param trackMessge
     * @return
     */
    private String getTrackingStringByCode(String code, String trackMessge) {

        OrdOrderStatusCode statusCode = statusCodeService.getByCode(code);
        if (null != statusCode) {
            return getTrackingString(statusCode.getMessageTemplate(), trackMessge);
        }

        return null;
    }


    /**
     * 获取一个服务商给一个订单下面的子订单返回的对应状态的子订单的单号
     *
     * @param waybillNo  订单编号
     * @param serviceUid 服务商的编号
     * @param status     事件状态
     * @return
     */
    @Override
    public List<String> getFinishedSubOrdNos(String waybillNo, String serviceUid, Integer status) {
        ParamData pd = new ParamData();
        pd.put("waybillNo", waybillNo);
        pd.put("serviceUid", serviceUid);
        pd.put("status", status);
        List<String> list = dao.findForList(getSqlName("getFinishedSubOrdNos"), pd, String.class);
        return list;
    }

    /**
     * 获取当前时间前的上一条tracking记录
     *
     * @param waybillNo
     * @param serviceUid
     * @param date
     * @return
     */
    @Override
    public OrdOrderTracking getLastTracking(String waybillNo, String serviceUid, Date date) {
        ParamData pd = new ParamData();
        pd.put("waybillNo", waybillNo);
        pd.put("serviceUid", serviceUid);
        pd.put("createTime", date);
        OrdOrderTracking ordOrderTracking = (OrdOrderTracking) dao.findForObject(getSqlName("getLastTracking"), pd);
        return ordOrderTracking;
    }


    @Override
    public void checkCode(int sid, String waybillNo) {
        ParamData pd = new ParamData();
        pd.put("id", sid);
        pd.put("waybillNo", waybillNo);
        int count = (Integer) dao.findForObject(getSqlName("findCountByCode"), pd);
        if (count > 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_CODE_EXIST, "");
        }
    }

    /**
     * 1. 组装父类信息（基本信息）
     * 2. 组装本类特有的信息
     *
     * @param waybillNo
     * @return
     */
    @Override
    public OrderTrackingToServiceDto processOrderTrackMessage(String waybillNo) {
        OrdOrderDto ordOrderDto = orderService.findDtoByWaybillNo(waybillNo);

        OrderTrackingToServiceDto dto = new OrderTrackingToServiceDto();

        Map<String, String> sysDictUnitWeightMap = dictService.findMapByCatalog(CommCodes.SYS_DICT_BIZ_UNIT_WEIGHT);
        /**
         * 组装父类信息
         */
        TrackingToServiceDto trackingToServiceDto = processTrackMessage(ordOrderDto);
        EntityUtils.copyPropertiesIgnoreNull(trackingToServiceDto, dto);
        /**
         * 组装本类其他信息
         */
        List<String> subOrderWaybillNos = Lists.newArrayList();
        List<OrdSubOrderDto> subOrderDtoList = ordOrderDto.getOrdSubOrderDtos();
        if (null != subOrderDtoList && !subOrderDtoList.isEmpty()) {
            subOrderDtoList.forEach(ordSubOrderDto -> {
                subOrderWaybillNos.add(ordSubOrderDto.getSubOrderNo());
            });
        }
        dto.setSubOrders(ordOrderDto.getOrdSubOrderDtos());
        dto.setWeight(ordOrderDto.getCusWeight());
        dto.setWeightUnit(ordOrderDto.getCusWeightUnit());
        dto.setWeightUnitName(sysDictUnitWeightMap.get(dto.getWeightUnit()));
        dto.setPackageNum(ordOrderDto.getPackageNum());
        dto.setCargoTypeName(ordOrderDto.getCargoTypeName());

        //拼装明细
        List<OrdOrderCargoDto> cargoDtosList = ordOrderDto.getOrderCargoDtos();
        if (null != cargoDtosList && !cargoDtosList.isEmpty()) {
            List<OrdCargoToServiceDto> dtos = Lists.newArrayList();
            cargoDtosList.forEach(ordOrderCargoDto -> {
                OrdCargoToServiceDto ordCargoToServiceDto = new OrdCargoToServiceDto();
                EntityUtils.copyPropertiesIgnoreNull(ordOrderCargoDto, ordCargoToServiceDto);
                ordCargoToServiceDto.setGoodsNum(ordOrderCargoDto.getGoodsNumber());
                ordCargoToServiceDto.setGoodsUnit(ordOrderCargoDto.getGoodsUnit());
                ordCargoToServiceDto.setGoodsUnitName(sysDictUnitWeightMap.get(ordOrderCargoDto.getGoodsUnit()));
                dtos.add(ordCargoToServiceDto);
            });
            dto.setCargoList(dtos);

        }
        return dto;
    }


    /**
     * 根据订单号，子单号组装子单的信息dto
     *
     * @return
     */
    @Override
    public TrackingToSupOrder processSubOrderTracking(String orderNo) {

        OrdOrderDto orderDto = orderService.findDtoByOrderNo(orderNo);
        //组装父类信息
        TrackingToSupOrder trackingToSupOrder = new TrackingToSupOrder();
        trackingToSupOrder.setCargoType(orderDto.getCargoType());

        String strFromAddress = null;
        String strToAddress = null;
        String strFetchAddress = null;
        OrderAddressModel fromAddress = orderDto.getFromAddress();
        OrderAddressModel toAddress = orderDto.getToAddress();
        OrderAddressModel fetchAddress = orderDto.getFetchAddress();
        if (LanguageCode.CN_UPPER.equals(orderDto.getFromAddress().getCountryCode())) {
            if (!ObjectUtils.isEmpty(fromAddress)) {
                strFromAddress = fromAddress.getProvinceName() + fromAddress.getCityName() + fromAddress.getDistrictName() + fromAddress.getStreetName() + fromAddress.getAddress();
            }
            if (!ObjectUtils.isEmpty(toAddress)) {
                strToAddress = toAddress.getProvinceName() + toAddress.getCityName() + toAddress.getDistrictName() + toAddress.getStreetName() + toAddress.getAddress();
            }
            if (!ObjectUtils.isEmpty(fetchAddress)) {
                strFetchAddress = fetchAddress.getProvinceName() + fetchAddress.getCityName() + fetchAddress.getDistrictName() + fetchAddress.getStreetName() + fetchAddress.getAddress();
            }
        } else {
            if (!ObjectUtils.isEmpty(fromAddress)) {
                strFromAddress = fromAddress.getCityName();
            }
            if (!ObjectUtils.isEmpty(toAddress)) {
                strToAddress = toAddress.getCityName();
            }
            if (!ObjectUtils.isEmpty(fetchAddress)) {
                strFetchAddress = fetchAddress.getCityName();
            }
        }

        trackingToSupOrder.setFromAddress(strFromAddress);
        trackingToSupOrder.setFrom(orderDto.getFromName());
        trackingToSupOrder.setFromContact(orderDto.getFromPhone());


        trackingToSupOrder.setToAddress(strToAddress);
        trackingToSupOrder.setTo(orderDto.getToName());
        trackingToSupOrder.setToContact(orderDto.getToPhone());


        trackingToSupOrder.setFetchAddress(strFetchAddress);
        trackingToSupOrder.setFetch(orderDto.getToName());
        trackingToSupOrder.setFetchContact(orderDto.getToPhone());

        trackingToSupOrder.setOrderTime(orderDto.getCreateTime());
        trackingToSupOrder.setTotalWeight(orderDto.getFeeCalcWeight());
        trackingToSupOrder.setWaybillNo(orderDto.getWaybillNo());
        trackingToSupOrder.setPackageNum(orderDto.getPackageNum());
        List<TrackingToSupSubOrder> trackingToSupSubOrders = new ArrayList<>();
        //组装本类信息
        List<OrdSubOrder> subOrderList = subOrderService.findByOrderNo(orderNo);
        for (OrdSubOrder subOrder : subOrderList) {
            TrackingToSupSubOrder trackingSupSubOrder = new TrackingToSupSubOrder();
            trackingSupSubOrder.setCargoNumber(subOrder.getCargoNumber());
            trackingSupSubOrder.setHeight(subOrder.getHeight());
            trackingSupSubOrder.setLength(subOrder.getLength());
            trackingSupSubOrder.setSubWaybillNo(subOrder.getSubOrderNo());
            trackingSupSubOrder.setWeight(subOrder.getWeight());
            trackingSupSubOrder.setWidth(subOrder.getWidth());
            trackingToSupSubOrders.add(trackingSupSubOrder);
        }
        trackingToSupOrder.setTrackingToSupSubOrders(trackingToSupSubOrders);
        return trackingToSupOrder;
    }

    /**
     * 处理系统给供应商下发的tracking的基本信息
     *
     * @param ordOrderDto
     * @return
     */
    private TrackingToServiceDto processTrackMessage(OrdOrderDto ordOrderDto) {
        TrackingToServiceDto dto = new TrackingToServiceDto();
        String senderAddress;
        String receiverAddress;
        OrderAddressModel fromAddress = ordOrderDto.getFromAddress();
        OrderAddressModel toAddress = ordOrderDto.getToAddress();
        if (LanguageCode.CN_UPPER.equals(ordOrderDto.getFromAddress().getCountryCode())) {
            senderAddress = fromAddress.getProvinceName() + fromAddress.getCityName() + fromAddress.getDistrictName() + fromAddress.getStreetName() + fromAddress.getAddress();
            receiverAddress = toAddress.getProvinceName() + toAddress.getCityName() + toAddress.getDistrictName() + toAddress.getStreetName() + toAddress.getAddress();
        } else {
            senderAddress = fromAddress.getCityName();
            receiverAddress = toAddress.getCityName();
        }
        dto.setSenderAddress(senderAddress);
        dto.setReceiverAddress(receiverAddress);
        dto.setWaybillNo(ordOrderDto.getWaybillNo());
        dto.setSenderName(ordOrderDto.getFromName());
        dto.setSenderContact(ordOrderDto.getFromPhone());
        dto.setReceiverName(ordOrderDto.getToName());
        dto.setReceiverContact(ordOrderDto.getToPhone());
        return dto;
    }

    /**
     * 物流返回信息包括了物流信息，揽货的供应商返回物流信息同时，还有子单的信息.
     * 1. 保存物流信息
     * 2. 处理订单和子单的信息和状态
     * 3. 处理当前服务-供应商的工作是否完成：
     * 从tracking表中找到当前服务商对当前订单对应的子订单中收到了已经完成状态的子订单号finishedSubOrdNos，
     * 从子订单表中找到当前订单所有的子订单号originalSubOrdNos，
     * 如果finishedSubOrdNos 全部包含的有originalSubOrdNos,则表示这个服务商的工作已经完成，更新这个服务商的服务状态为已经完成
     * 4.是否向下一个服务商产生服务商订单
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public OrdTrackingResult processAfterTracking(TrackingSupOrder trackingSupOrder) {
        OrdTrackingResult trackingResult = new OrdTrackingResult();
        //1、根据waybillNo获取订单信息
        OrdOrder order = orderService.findByWaybillNo(trackingSupOrder.getWaybillNo());
        if (ObjectUtils.isEmpty(order)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "获取订单数据异常");
        }
        OrdOrder originalOrder = new OrdOrder();
        BeanUtils.copyProperties(order, originalOrder);
        trackingSupOrder.setOrderNo(order.getOrderNo());
        //2、当物流表中已经有消息时，再发的消息就忽略了。
        List<OrdOrderTracking> ordOrderTrackingList = this.findByWaybillNo(trackingSupOrder.getWaybillNo(), trackingSupOrder.getCode(), trackingSupOrder.getServiceUid(), 0);
        if (!CollectionUtils.isEmpty(ordOrderTrackingList)) {
            trackingResult.setSuccess(false);
            trackingResult.setReason(ErrorCodes.ERROR_ORD_TRACKING_CODE_DUPLICATE.getCode());
            return trackingResult;
        }
        //3、
        OrdOrderStatusCode statusCode = orderStatusCodeService.getByCode(trackingSupOrder.getCode());
        if (ObjectUtils.isEmpty(statusCode)) {
            trackingResult.setSuccess(false);
            trackingResult.setReason(ErrorCodes.ERROR_ORD_TRACKING_CODE_NOT_EXIST.getCode());
            return trackingResult;
        }
        if (!ObjectUtils.isEmpty(statusCode.getOrderStatus())
                && order.getOrderStatus().compareTo(statusCode.getOrderStatus()) > 0) {
            trackingResult.setSuccess(false);
            trackingResult.setReason(ErrorCodes.ERROR_ORD_TRACKING_STATUS_EXCEPTION.getCode());
            return trackingResult;
        }
        //获取数据库中子单的个数
        List<String> subOrderNoList = subOrderService.getSubOrdNos(order.getOrderNo());
        //获取物流中子单的个数
        List<TrackingSupSubOrder> trackingSupSubOrders = trackingSupOrder.getTrackingSupSubOrders();
        List<String> trackingSubOrderNoList = new ArrayList<>();
        for (TrackingSupSubOrder trackingSupSubOrder : trackingSupSubOrders) {
            trackingSubOrderNoList.add(trackingSupSubOrder.getSubOrderNo());
        }

        //判断两者是否一致，不一致，则物流消息无效
        trackingSubOrderNoList = CollectionUtils.removeDuplication(trackingSubOrderNoList);
        if (trackingSubOrderNoList.size() != subOrderNoList.size()) {
            trackingResult.setSuccess(false);
            trackingResult.setReason(ErrorCodes.ERROR_ORD_TRACKING_SUBORDER_NUMBER_EXCEPTION.getCode());
            return trackingResult;
        }


        //1、验证serviceUid、supplerId的有效性
        if (!ObjectUtils.isEmpty(trackingSupOrder.getServiceUid())) {
            orderService.validateServiceUid(order, trackingSupOrder.getServiceUid(), trackingSupOrder.getSupplierId());
        }

        List<OrdSubOrder> origSubOrderList = subOrderService.findBySubOrderNos(subOrderNoList);

        //4、更新订单和子订单的状态、长、宽、高、体积重、计费重信息，并重新分派服务
        trackingResult = orderService.processOrderInfoByTracking(trackingSupOrder, order);

        //8、日志相关的操作
        List<OrdSubOrder> subOrderList = subOrderService.findBySubOrderNos(subOrderNoList);
        List<OrdOrderTracking> orderTrackingList = new ArrayList<>();
        if (trackingResult.isSuccess()) {
            //给子单添加物流消息
            for (OrdSubOrder subOrder : subOrderList) {
                OrdOrderTracking orderTracking = new OrdOrderTracking();
                EntityUtils.copyPropertiesIgnoreNull(trackingSupOrder, orderTracking);
                if (null == orderTracking.getOriginalId()) {
                    orderTracking.setOriginalId(0);
                }
                orderTracking.setSubOrderNo(subOrder.getSubOrderNo());
                orderTrackingList.add(orderTracking);
            }
            this.batchSave(orderTrackingList);
        }


        //5、根据物流消息判断是否需要向下一个供应商发消息,如果物流消息发的是309消息，那么不需要执行这一步
        if (trackingResult.isSuccess()) {
            serviceOrderService.processAfterTracking(trackingSupOrder.getStatus(), trackingSupOrder.getCode(), trackingSupOrder.getServiceUid(), order);
        }

        //6、保存物流的日志信息(包括：日志、操作日志)
        this.saveTrackingOperLog(trackingSupOrder, order, originalOrder, origSubOrderList, subOrderList, orderTrackingList);

        return trackingResult;
    }

    private void saveTrackingOperLog(TrackingSupOrder trackingSupOrder, OrdOrder order, OrdOrder originalOrder, List<OrdSubOrder> origSubOrderList, List<OrdSubOrder> subOrderList, List<OrdOrderTracking> orderTrackingList) {
        //6、保存日志信息
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_ORDER_TRACKING", trackingSupOrder);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_TRACKING, UserActions.ADD, "添加物流的跟踪信息", dataBackup);

        //7、记录操作日志 add 2017-10
        Integer accountId = PrincipalUtils.getAccountId();
        Integer domainId = PrincipalUtils.getDomainId();


        Map<String, OrdSubOrder> subOrderMap = EntityUtils.getStringKeyMapFromBeans(subOrderList, "subOrderNo");
        Map<String, OrdSubOrder> origSubOrderMap = EntityUtils.getStringKeyMapFromBeans(origSubOrderList, "subOrderNo");
        Map<String, OrdOrderTracking> orderTrackingMap = EntityUtils.getStringKeyMapFromBeans(orderTrackingList, "subOrderNo");
        Set<String> subOrderNoSet = subOrderMap.keySet();
        for (String subOrderNo : subOrderNoSet) {
            operationLogService.saveOrdLogisInfoUpdateLog(order.getId(), origSubOrderMap.get(subOrderNo), subOrderMap.get(subOrderNo), originalOrder, order, UserActions.ADD, OrdOperationLogEnum.LOGISTICS_INFO_UPDATE, orderTrackingMap.get(subOrderNo), accountId, domainId);
        }
    }


    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    @Override
    public void processReceGoodTracking(List<OrdTrackingTransDto> trackingTransDtoList) {
        //1、根据传递过来的数据提取出后面要处理时的共用数据waybillNos、supplierIds、subOrderNos、codeList
        List<String> waybillNos = new ArrayList<>();//要处理的订单号集合
        List<Integer> supplierIds = new ArrayList<>();//供应商的集合
        List<String> subOrderNos = new ArrayList<>();//子订单集合
        List<String> codeList = new ArrayList<>();
        for (OrdTrackingTransDto trackingTransDto : trackingTransDtoList) {
            codeList.add(trackingTransDto.getCode());
            waybillNos.add(trackingTransDto.getWaybillNo());
            supplierIds.add(trackingTransDto.getSupplierId());
            List<OrdTrackingTransSubOrderDto> trackingTransSubOrderDtoList = trackingTransDto.getSubOrder();
            for (OrdTrackingTransSubOrderDto subOrderDto : trackingTransSubOrderDtoList) {
                subOrderNos.add(subOrderDto.getSubOrderNo());
            }
        }
        waybillNos = CollectionUtils.removeDuplication(waybillNos);
        subOrderNos = CollectionUtils.removeDuplication(subOrderNos);
        supplierIds = CollectionUtils.removeDuplication(supplierIds);
        codeList = CollectionUtils.removeDuplication(codeList);

        //2、根据上面提取的共用数据，查找出订单集合、子订单集合、serviceUid的集合，并转换成对应的Map对象
        //查询订单
        List<OrdOrder> ordOrderList = orderService.findByOrderNos(waybillNos);
        if (waybillNos.size() != ordOrderList.size()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_WAYBILLNO_NOT_EQ);
        }
        //查询子订单
        List<OrdSubOrder> subOrderList = subOrderService.findBySubOrderNos(subOrderNos);
        if (subOrderNos.size() != subOrderList.size()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_SUBWAYBILLNO_NOT_EQ);
        }
        //查询对应的serviceUid
        List<OrdTrackingMessage> trackingMessageList = trackingMessageService.findServiceUidByWaybillNos(waybillNos, supplierIds);
        if (waybillNos.size() != trackingMessageList.size()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_SERVICEUID_NOT_FOUND);
        }
        //查询code
        OrdOrderStatusCode statusCode = this.getOrderStatusCode(codeList);
        //转换为map
        Map<String, OrdOrder> ordOrderMap = EntityUtils.getStringKeyMapFromBeans(ordOrderList, "waybillNo");
        Map<String, OrdSubOrder> subOrderMap = EntityUtils.getStringKeyMapFromBeans(subOrderList, "subOrderNo");
        Map<String, OrdTrackingMessage> trackingMessageMap = EntityUtils.getStringKeyMapFromBeans(trackingMessageList, "waybillNo");

        //3、拼装物流信息、添加订单及子订单的长宽高及单位、状态等信息
        List<OrdOrderTracking> orderTrackingList = new ArrayList<>();//要保存的物流信息集合
        for (OrdTrackingTransDto trackingTransDto : trackingTransDtoList) {
            String waybillNo = trackingTransDto.getWaybillNo();
            OrdOrder ordOrder = ordOrderMap.get(waybillNo);
            this.processData(statusCode, subOrderMap, trackingMessageMap, orderTrackingList, trackingTransDto, waybillNo, ordOrder);
        }

        //4、保存物流信息与子订单信息
        this.batchSave(orderTrackingList);
        subOrderService.batchUpdate(subOrderList);

        //5、保存订单的信息
        List<OrdSubOrder> subOrderStatusList = subOrderService.getMinStatusByOrderNos(waybillNos);
        for (OrdSubOrder subOrder : subOrderStatusList) {
            OrdOrder ordOrder = ordOrderMap.get(subOrder.getOrderNo());
            if (ordOrder.getOrderStatus().compareTo(subOrder.getOrderStatus()) > 0) {
                throw Exceptions.bizException(ErrorCodes.ERROR_SUBWAYBILLNO_STATUS_EXCEPTION);
            } else if (ordOrder.getOrderStatus().compareTo(subOrder.getOrderStatus()) < 0) {
                ordOrder.setOrderStatus(subOrder.getOrderStatus());
                ordOrder.setReceiveCargoTime(dao.getDbDate());
            }
        }
        orderService.batchUpdate(ordOrderList);

        //6、调用计费接口保存计费数据
        List<OrdOrder> feeCalcList = new ArrayList<>();
        for (OrdOrder order : ordOrderList) {
            QuotationCalcResult result = calcService.calcWaybillFeeWeight(order.getWaybillNo());
            if (!ObjectUtils.isEmpty(result)) {
                order.setFeeCalcWeight(result.getFeeWeight());
                order.setFeeCalcWeightUnit(result.getFeeWeightUnitCode());
                feeCalcList.add(order);
            }
        }
        orderService.batchUpdate(feeCalcList);
    }

    private void processData(OrdOrderStatusCode statusCode, Map<String, OrdSubOrder> subOrderMap, Map<String, OrdTrackingMessage> trackingMessageMap, List<OrdOrderTracking> orderTrackingList, OrdTrackingTransDto trackingTransDto, String waybillNo, OrdOrder ordOrder) {
        //3.1、设置订单的总重与单位
        if (!ObjectUtils.isEmpty(trackingTransDto.getTotalWeight()) &&
                !ObjectUtils.isEmpty(trackingTransDto.getTotalWeightUnit())) {//当重量与重量的单位同时不为空时，才做更新处理
            ordOrder.setSupWeight(trackingTransDto.getTotalWeight());
            ordOrder.setSupWeightUnit(trackingTransDto.getTotalWeightUnit());
        }

        //3.2、拼装物流ordOrderTracking对象信息,并设置订单与子订单的长宽高及单位信息
        OrdOrderTracking parentOrderTracking = new OrdOrderTracking();
        parentOrderTracking.setOriginalId(trackingTransDto.getOriginalId());
        parentOrderTracking.setCode(OrderStatus.RECEGOOD.getCode());
        parentOrderTracking.setType(CommCodes.TRACKING_TYPE_SUPPER);
        parentOrderTracking.setStatus(trackingTransDto.getStatus());
        parentOrderTracking.setWaybillNo(waybillNo);
        parentOrderTracking.setMessageTime(trackingTransDto.getMessageTime());
        parentOrderTracking.setServiceUid(trackingMessageMap.get(waybillNo).getServiceUid());
        parentOrderTracking.setSupplierId(trackingTransDto.getSupplierId());
        parentOrderTracking.setTrackMessage(trackingTransDto.getTrackMessage());
        List<OrdTrackingTransSubOrderDto> trackingTransSubOrderDtoList = trackingTransDto.getSubOrder();
        for (OrdTrackingTransSubOrderDto subOrderDto : trackingTransSubOrderDtoList) {
            //3.2.1、从子单中拼接Ord_Order_Tracking数据信息
            OrdOrderTracking orderTracking = new OrdOrderTracking();
            EntityUtils.copyPropertiesIgnoreNull(parentOrderTracking, orderTracking);
            orderTracking.setServiceOrderNo(subOrderDto.getServiceOrderNo());
            orderTracking.setSubOrderNo(subOrderDto.getSubOrderNo());
            orderTrackingList.add(orderTracking);
            //3.2.2、对子单中的长、宽、高、重量、及其单位做更新
            OrdSubOrder subOrder = subOrderMap.get(subOrderDto.getSubOrderNo());
            subOrder.setCargoNumber(subOrderDto.getCargoNumber());//子订单中货物的件数
            if (!ObjectUtils.isEmpty(subOrderDto.getLength()) && !ObjectUtils.isEmpty(subOrderDto.getWidth()) &&
                    !ObjectUtils.isEmpty(subOrderDto.getHeight()) && !ObjectUtils.isEmpty(subOrderDto.getLwhUnit())) {//更新长宽高
                subOrder.setLwhUnit(subOrderDto.getLwhUnit().toLowerCase());
                subOrder.setLength(subOrderDto.getLength());
                subOrder.setWidth(subOrderDto.getWidth());
                subOrder.setHeight(subOrderDto.getHeight());
            }
            if (!ObjectUtils.isEmpty(subOrderDto.getWeight()) && !ObjectUtils.isEmpty(subOrderDto.getWeightUnit())) {//更新重量
                subOrder.setWeightUnit(subOrderDto.getWeightUnit().toLowerCase());
                subOrder.setWeight(subOrderDto.getWeight());
            }
            //3.3.3、如果供应商发过来的订单状态比子订单状态落后，代表数据有问题，不处理,否则保存子订单的状态信息
            if (statusCode.getOrderStatus().compareTo(subOrder.getOrderStatus()) < 0) {
                throw Exceptions.bizException(ErrorCodes.ERROR_SUBWAYBILLNO_STATUS_EXCEPTION);
            }
            subOrder.setOrderStatus(statusCode.getOrderStatus());
        }
    }

    private OrdOrderStatusCode getOrderStatusCode(List<String> codeList) {
        OrdOrderStatusCode statusCode;
        if (codeList.size() != 1) {
            throw Exceptions.bizException(ErrorCodes.ERROR_WAYBILLNO_STATUS_EXCEPTION);
        }
        statusCode = orderStatusCodeService.getByCode(codeList.get(0));
        if (ObjectUtils.isEmpty(statusCode)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_WAYBILLNO_STATUS_EXCEPTION);
        }
        if (!statusCode.getOrderStatus().equals(OrderStatus.RECEGOOD)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_WAYBILLNO_STATUS_EXCEPTION);
        }
        return statusCode;
    }


    /**
     * 处理供应商发给三藏平台正常的物流信息
     *
     * @param orderNormalTrackingDtos
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void processNomarlTracking(List<OrderNormalTrackingDto> orderNormalTrackingDtos, String batchNo) {
        //1、获取会影响订单状态的物流编码
        List<String> reviseStatusList = new ArrayList<>();
        Map<String, OrderStatus> ordOrderStatusCodeMap = new HashMap<>();
        orderStatusCodeService.findReviseStatus().forEach(ordOrderStatusCode -> {
            reviseStatusList.add(ordOrderStatusCode.getCode());
            ordOrderStatusCodeMap.put(ordOrderStatusCode.getCode(), ordOrderStatusCode.getOrderStatus());
        });

        //2、获取订单、子订单对应的实体信息并放入map，后面使用
        Set<String> waybillNoSet = new HashSet<>();
        Set<String> allSubOrderNoSet = new HashSet<>();
        orderNormalTrackingDtos.forEach(orderNormalTrackingDto -> {
            waybillNoSet.add(orderNormalTrackingDto.getWaybillNo());
            allSubOrderNoSet.addAll(orderNormalTrackingDto.getSubOrderNo());
        });
        Map<String, OrdOrder> ordOrderMap = EntityUtils.getStringKeyMapFromBeans(orderService.findByOrderNos(new ArrayList<>(waybillNoSet)), "waybillNo");
        //组装子订单为Map对象
        List<OrdSubOrder> subOrderList = subOrderService.findBySubOrderNos(new ArrayList<>(allSubOrderNoSet));
        Map<String, List<OrdSubOrder>> subOrderMap = new HashMap<>();
        for (OrdSubOrder ordSubOrder : subOrderList) {
            if (subOrderMap.get(ordSubOrder.getOrderNo()) == null) {
                subOrderMap.put(ordSubOrder.getOrderNo(), new ArrayList<>());
            }
            subOrderMap.get(ordSubOrder.getOrderNo()).add(ordSubOrder);
        }


        //3、拼装物流信息做保存，如果物流状态影响现在的订单状态，那么给下个供应商下单
        List<OrdOrderTracking> preOrderTrackingList = new ArrayList<>();//保存传递过来的物流信息
        List<OrdTrackingMessage> nextOrderTrackingList = new ArrayList<>();//保存给下个供应商生成的物流信息
        Map<String, OrderStatus> updateSubOrderMap = new HashMap<>();//要更新子订单的map集合
        Set<String> updateOrderSet = new HashSet<>(); //要更新的订单集合
        for (OrderNormalTrackingDto orderNormalTrackingDto : orderNormalTrackingDtos) {
            OrdOrder order = ordOrderMap.get(orderNormalTrackingDto.getWaybillNo());
            //3.1、获取订单状态orderStatus
            OrderStatus orderStatus = null;
            if (reviseStatusList.contains(orderNormalTrackingDto.getCode())) {
                orderStatus = ordOrderStatusCodeMap.get(orderNormalTrackingDto.getCode());
            }
            //3.2、获取下个服务商的service
            Service service = null;
            if (orderNormalTrackingDto.getStatus().compareTo(CommCodes.TRACKING_STATUS_FINISH) == 0) {
                service = this.getService(orderNormalTrackingDto.getSupplierId(), orderNormalTrackingDto.getWaybillNo());
            }
            //3.3、每个子子订单组装成一条物流信息，然后保存
            for (String subOrderNo : orderNormalTrackingDto.getSubOrderNo()) {
                //3.2.1、保存传递过来的物流消息
                OrdOrderTracking orderTracking = new OrdOrderTracking();
                EntityUtils.copyPropertiesIgnoreNull(orderNormalTrackingDto, orderTracking);
                orderTracking.setSubOrderNo(subOrderNo);
                preOrderTrackingList.add(orderTracking);
                //3.2.2、组装新的物流消息给下个供应商
                if (orderNormalTrackingDto.getStatus().intValue() == 1 && !ObjectUtils.isEmpty(service)) {
                    //通知下个供应商来继续取货
                    OrdTrackingMessage trackingMessage = new OrdTrackingMessage();
                    //设置原始物流信息的id为0，表示没有原始物流信息
                    trackingMessage.setMessageTime(dao.getDbDate());
                    trackingMessage.setServiceUid(service.getUid());
                    trackingMessage.setEventCode(TrackMessageToServiceEnum.PLACE_TRADE_ORDER.getCode());
                    trackingMessage.setStatus(OrderTrackingConstants.TrackingStatus.TRACKING_STATUS_NUSYNC);
                    trackingMessage.setSupplierId(service.getSupplierId());
                    TrackingToSupOrder dto = this.processSubOrderTracking(order.getOrderNo());
                    trackingMessage.setTrackingReport(JsonUtils.toJSONString(dto));
                    trackingMessage.setType(OrderTrackingConstants.TrackingType.TRACKING_TYPE_SYSTEM);
                    trackingMessage.setWaybillNo(order.getWaybillNo());
                    trackingMessage.setDescription("物流消息");
                    nextOrderTrackingList.add(trackingMessage);
                }
            }
            //3.4、判断要保存的子单状态是否与原有的状态冲突
            if (orderStatus != null) {
                for (OrdSubOrder subOrder : subOrderMap.get(orderNormalTrackingDto.getWaybillNo())) {
                    updateSubOrderMap.put(subOrder.getSubOrderNo(), orderStatus);
                    updateOrderSet.add(subOrder.getOrderNo());
                    if (orderStatus.compareTo(subOrder.getOrderStatus()) < 0) {
                        throw Exceptions.bizException(CommonErrorCodes.ERROR_COMMON, "订单状态异常");
                    }
                }
            }

        }

        //保存物流信息
        this.batchSave(preOrderTrackingList);
        trackingMessageService.batchSave(nextOrderTrackingList);

        //更新子订单与订单的状态
        if (!CollectionUtils.isEmpty(updateSubOrderMap)) {//如果updateSubOrderNoMap不为null，代表物流会影响子订单状态
            updateOrderStatus(ordOrderMap, updateSubOrderMap, updateOrderSet);
        }

        //4、保存日志信息
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_ORDER_TRACKING", orderNormalTrackingDtos);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_TRACKING, UserActions.ADD, "添加物流的跟踪信息", dataBackup);
    }

    private void updateOrderStatus(Map<String, OrdOrder> ordOrderMap, Map<String, OrderStatus> updateSubOrderNoMap, Set<String> updateOrderNoList) {
        //更新子子订单状态
        subOrderService.updateOrderStatus(updateSubOrderNoMap);//更新子订单的状态

        //更新订单的状态
        List<OrdSubOrder> subOrderList = subOrderService.getMinStatusByOrderNos(new ArrayList<>(updateOrderNoList));
        Map<String, OrderStatus> updateOrderStatusMap = new HashMap<>();
        for (OrdSubOrder ordSubOrder : subOrderList) {
            String waybillNo = ordSubOrder.getOrderNo();
            if (ordOrderMap.get(waybillNo).getOrderStatus().compareTo(ordSubOrder.getOrderStatus()) < 0) {
                updateOrderStatusMap.put(ordSubOrder.getOrderNo(), ordSubOrder.getOrderStatus());
            }
        }
        orderService.updateOrderStatus(updateOrderStatusMap);
    }

    private Service getService(int supplierId, String waybillNo) {
        //得到订单的订单号
        String orderNo = orderService.findOrderNoByWaybillNo(waybillNo);
        //获取上个serviceUid
        String serviceUid = trackingMessageService.findServiceUidByWaybillNo(orderNo, supplierId);
        if (StringUtils.isEmpty(serviceUid)) {
            throw Exceptions.bizException(CommonErrorCodes.ERROR_COMMON, "系统错误");
        }
        //获取下一个service信息
        Service service = null;
        OrdOrderOptionService orderOptionService = orderServiceAssignService.findNextServices(orderNo, serviceUid);
        if (!ObjectUtils.isEmpty(orderOptionService)) {//如果还有下一个服务----供应商
            service = serviceService.findActivedByUid(orderOptionService.getServiceUid());//得到服务商的
        }
        return service;
    }

    /**
     * 根据条件生成要保存的物流信息与要给下个供应商下发的物流信息
     *
     * @param batchNo
     * @param ordOrderTrackingList
     * @param newOrderTrackingList
     * @param orderNormalTrackingDto
     * @param service
     */
    private void generateTracking(String batchNo, List<OrdOrderTracking> ordOrderTrackingList, List<OrdOrderTracking> newOrderTrackingList, OrderNormalTrackingDto orderNormalTrackingDto, Service service) {
       /* //3.2、每个子子订单组装成一条物流信息，然后保存
        for (String subOrderNo : orderNormalTrackingDto.getSubOrderNo()) {
            //3.2.1、保存传递过来的物流消息
            OrdOrderTracking orderTracking = new OrdOrderTracking();
            EntityUtils.copyPropertiesIgnoreNull(orderNormalTrackingDto, orderTracking);
            orderTracking.setSubOrderNo(subOrderNo);
            ordOrderTrackingList.add(orderTracking);
            //3.2.2、组装新的物流消息给下个供应商
            if (orderNormalTrackingDto.getStatus().intValue() == 1 && !ObjectUtils.isEmpty(service)) {
                OrdOrderTracking newOrderTracking = new OrdOrderTracking();
                newOrderTracking.setBatchNo(batchNo);
                newOrderTracking.setCode(TrackMessageToServiceEnum.CARGO_TRANSPORT.getCode());
                newOrderTracking.setType(CommCodes.TRACKING_TYPE_SYSTEM);
                newOrderTracking.setStatus(CommCodes.TRACKING_STATUS_FINISH);//我们发给服务商的，默认为2
                newOrderTracking.setWaybillNo(orderNormalTrackingDto.getWaybillNo());
                newOrderTracking.setSubOrderNo(subOrderNo);
                newOrderTracking.setMessageTime(dao.getDbDate());
                newOrderTracking.setServiceUid(service.getUid());
                newOrderTracking.setSupplierId(service.getSupplierId());
                SubOrderTrackingToServiceDto dto = this.processSubOrderTracking(newOrderTracking);
                newOrderTracking.setTrackMessage(JsonUtils.toJSONString(dto));
                newOrderTrackingList.add(newOrderTracking);
            }
        }*/
    }


    /**
     * 根据订单号，给对应的服务-供应商发送订单的信息
     * (修改订单信息后，手动推送的)
     *
     * @param waybillNo
     * @param serviceUid
     */
    @Override
    public void addMsgAfterUpdateOrder(String waybillNo, String serviceUid, Integer supplierId) {
        /**
         * 1.检查订单号是否有效
         */
        OrdOrder ordOrder = orderService.findByOrderNo(waybillNo);
        if (null == ordOrder) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "此订单不存在");
        }
        /**
         * 2.检查服务商是否有效
         */
        boolean flag = orderService.validateServiceUid(ordOrder, serviceUid, supplierId);
        /**
         * 3.供应商有效，下发信息
         */
        if (flag) {
            OrdTrackingMessage trackingMessage = orderTrackingToService(ordOrder.getWaybillNo(), TrackMessageToServiceEnum.UPDATE_TRADE_ORDER.getCode(), CommCodes.TRACKING_TYPE_SYSTEM_KEFU, serviceUid, supplierId);
            ordTrackingMessageService.save(trackingMessage);
        } else {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "该服务商-供应商不属于该订单,请检查");
        }

    }

    /**
     * 人工添加子单的物流信息之后，给供应商发送的信息
     *
     * @param waybillNo
     * @param subOrderNo
     * @param serviceUid
     * @param supplierId
     */
    @Override
    public void addMsgAfterAddSubTracking(String waybillNo, String subOrderNo, String serviceUid, Integer supplierId) {

        /**
         * 1. 检查订单号是否有效
         */
        OrdOrder ordOrder = orderService.findByOrderNo(waybillNo); //根据订单号（waybillNo）获取当前的订单信息
        if (ObjectUtils.isEmpty(ordOrder)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "获取订单数据异常");
        }

        /**
         * 2.检查子单是否有效
         */
        OrdSubOrder oldSubOrder = subOrderService.findBySubOrderNo(subOrderNo);
        if (ObjectUtils.isEmpty(oldSubOrder)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "获取子订单数据异常");
        }

        /**
         * 检查供应商是否有效
         */
        boolean flag = orderService.validateServiceUid(ordOrder, serviceUid, supplierId);
        /**
         * 发送消息
         */
        if (flag) {
            OrdOrderTracking tracking = subOrderTrackingToService(ordOrder.getOrderNo(), subOrderNo, TrackMessageToServiceEnum.MSG_RESEND.getCode(), CommCodes.TRACKING_TYPE_SYSTEM_KEFU, serviceUid, supplierId, waybillNo);
            save(tracking);
        } else {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "该服务商-供应商不属于该订单,请检查");
        }
    }


    /**
     * 系统给供应商的消息
     *
     * @param waybillNo
     * @param code:      tracking类型
     * @param serviceUid
     * @param supplierId
     * @return
     */
    @Override
    public OrdTrackingMessage orderTrackingToService(String waybillNo, String code, int type, String serviceUid, int supplierId) {
        OrdTrackingMessage trackingMessage = new OrdTrackingMessage();
        trackingMessage.setEventCode(code);
        trackingMessage.setMessageTime(dao.getDbDate());
        trackingMessage.setStatus(CommCodes.TRACKING_SYN_STATUS_DEFAULT);
        trackingMessage.setSupplierId(supplierId);
        trackingMessage.setWaybillNo(waybillNo);
        trackingMessage.setServiceUid(serviceUid);
        trackingMessage.setType(type);
        //发件地址，发件人联系方式，货物类型，货物件数，货物体积，货物实重，货物明细，目的地，目标联系人
        OrderTrackingToServiceDto dto = this.processOrderTrackMessage(waybillNo);
        trackingMessage.setTrackingReport(JsonUtils.toJSONString(dto));
        return trackingMessage;
    }

    @Override
    public OrdOrderTracking subOrderTrackingToService(String orderNo, String subOrderNo, String code, int type, String serviceUid, int supplierId, String waybillNo) {
        OrdOrderTracking orderTracking = new OrdOrderTracking();
        //设置原始物流信息的id为0，表示没有原始物流信息
        orderTracking.setOriginalId(0);
        //通知服务商去揽货的code
        orderTracking.setCode(code);
        orderTracking.setType(type);
        orderTracking.setStatus(CommCodes.TRACKING_STATUS_FINISH);//我们发给服务商的，默认为2
        orderTracking.setOrderNo(orderNo);
        orderTracking.setWaybillNo(waybillNo);
        orderTracking.setSubOrderNo(subOrderNo);
        orderTracking.setMessageTime(dao.getDbDate());
        orderTracking.setServiceUid(serviceUid);
        orderTracking.setSupplierId(supplierId);
        //发件地址，发件人联系方式，货物类型，货物件数，货物体积，货物实重，货物明细，目的地，目标联系人
        TrackingToSupOrder dto = processSubOrderTracking(orderNo);
        orderTracking.setTrackMessage(JsonUtils.toJSONString(dto));
        return orderTracking;

    }


    private static String replaceMessage(String msg) {
        List<String> list = Lists.newArrayList();
        Pattern p = Pattern.compile(CommCodes.ORD_TRACKING_REGEX);

        Matcher m = p.matcher(msg);
        StringBuffer sb = new StringBuffer();
        int i = 0;
        while (m.find()) {
            list.add(String.valueOf(i));
            m.appendReplacement(sb, m.group().replace(m.group().substring(1, m.group().length() - 1), String.valueOf(i)));
            i++;
        }
        m.appendTail(sb);
        return sb.toString();
    }

//    public static void main(String[] args) {
//        replaceMessage("货物已到达【A地】，入仓完成");
//    }

    /**
     * 人工增加子单的物流信息（不含有供应商信息）
     * 1. 保存物流信息
     * 2. 修改子单和订单的状态
     *
     * @param dto
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

    public void addSubTracking(SubOrderTrackingDto dto) {
        //1、根据waybillNo获取订单信息
        OrdOrder oldOrder = orderService.findByOrderNo(dto.getOrderNo()); //根据订单号（waybillNo）获取当前的订单信息
        if (ObjectUtils.isEmpty(oldOrder)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "获取订单数据异常");
        }

        //2、根据subOrderNo获取子订单信息
        OrdSubOrder oldSubOrder = subOrderService.findBySubOrderNo(dto.getSubOrderNo());
        if (ObjectUtils.isEmpty(oldSubOrder)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "获取子订单数据异常");
        }

        //从code表获取这个code
        OrdOrderStatusCode code = statusCodeService.getByCode(dto.getCode());
        if (ObjectUtils.isEmpty(code)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "该物流信息不存在");
        }

        //处理是否需要参数
        String[] needParams = statusCodeService.getParams(code.getMessageTemplate());
        if (null != needParams && needParams.length > 0) {
            if (null == dto.getParams() || dto.getParams().length != needParams.length) {
                throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "消息参数不匹配");
            }
        }

        TrackingSupOrder trackingSupOrder = new TrackingSupOrder();
        trackingSupOrder.setCode(dto.getCode());
        //客服添加的
        trackingSupOrder.setType(CommCodes.TRACKING_TYPE_SYSTEM_KEFU);
        String waybillNo = orderService.findWaybillNoByOrderNo(dto.getOrderNo());
        trackingSupOrder.setWaybillNo(waybillNo);
        trackingSupOrder.setMessageTime(dto.getMessageTime());


        if (null != dto.getParams() && dto.getParams().length > 0) {
            StringBuilder trackMessage = new StringBuilder();

            for (int i = 0; i < dto.getParams().length; i++) {
                trackMessage.append(dto.getParams()[i].toString()).append("|");
            }
            String message = new String(trackMessage);
            message = message.substring(0, message.lastIndexOf("|"));
            trackingSupOrder.setTrackMessage(message);
        }

        String startcode = dto.getCode().substring(0, 1);
        if (startcode.equals(CommCodes.ORDERSTATUSCODE_STARTCODE4)) {
            if (dto.getCode().equals(CommCodes.ORDERSTATUSCODE_STARTCODE4_END1) || dto.getCode().equals(CommCodes.ORDERSTATUSCODE_STARTCODE4_END2)) {
                trackingSupOrder.setStatus(CommCodes.TRACKING_STATUS_FINISH);
            }
        } else if (startcode.equals(CommCodes.ORDERSTATUSCODE_STARTCODE6)) {
            if (dto.getCode().equals(CommCodes.ORDERSTATUSCODE_STARTCODE6_END2) || dto.getCode().equals(CommCodes.ORDERSTATUSCODE_STARTCODE6_END3) || dto.getCode().equals(CommCodes.ORDERSTATUSCODE_STARTCODE6_END4)) {
                trackingSupOrder.setStatus(CommCodes.TRACKING_STATUS_FINISH);
            }
        } else {

            //处理当前供应商对这个子单的工作是否已经完成，从code表中找到当前code的第一位数字开头的最大的code 如果当前code==最大code，则表示已经完成
            String maxCode = statusCodeService.getMaxCode(startcode, code.getOperType(), code.getType());
            if (maxCode.equals(dto.getCode())) {
                trackingSupOrder.setStatus(CommCodes.TRACKING_STATUS_FINISH);
            } else {
                trackingSupOrder.setStatus(CommCodes.TRACKING_STATUS_UNFINISH);
            }

        }
        OrdOrderTracking orderTracking = new OrdOrderTracking();
        EntityUtils.copyPropertiesIgnoreNull(trackingSupOrder, orderTracking);
        if (null == orderTracking.getOriginalId()) {
            orderTracking.setOriginalId(0);
        }
        this.save(orderTracking);
        //4、保存日志信息
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_ORDER_TRACKING", orderTracking);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_ORDER_TRACKING, UserActions.ADD, "添加物流的跟踪信息", dataBackup);

        //2
        orderService.processOrderInfoByTracking(trackingSupOrder, oldOrder);
        //3
        // serviceOrderService.processAfterTracking(orderTracking, oldOrder);


    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public List<String> addTracking(List<String> contentList, String code, List<String> param, Date messageTime, int type) {
        if (dao.getDbDate().compareTo(messageTime) < 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "时间应小于当前时间");
        }
        if (contentList.size() > 100) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "最多处理100条记录，当前条数为：" + contentList.size());
        }
        //得到前端传过来的waybillNos与subOrderNos集合,并判断是否有重复
        Set<String> orderNoSet = Sets.newHashSet();//前端传递过来的包含waybillNos的集合
        Set<String> subOrderNoSet = Sets.newHashSet();//前端传递过来的包含subOrderNos的集合
        List<String> notExitDataList = Lists.newArrayList();
        notExitDataList = this.processWaybillNos(contentList, orderNoSet, subOrderNoSet, type);

        //获取前端传递的订单和子订单中的不存在数据和为草稿状态的数据
        //List<String> notExitDataList = Lists.newArrayList();//不存在的订单或子订单集合
        List<String> draftDataList = Lists.newArrayList();//为草稿状态的订单或子订单集合
        List<OrdSubOrder> subOrderList = this.getNoProcessDataBySubOrderNo(subOrderNoSet, notExitDataList, draftDataList);
        this.getNoProcessDataByOrderNo(orderNoSet, notExitDataList, draftDataList);
       /* if (notExitDataList.size() > 0) {
            throw Exceptions.bizExceptionData(ErrorCodes.ERROR_COMMON, notExitDataList, "数据不存在！！");
        }
        if (draftDataList.size() > 0) {
            throw Exceptions.bizExceptionData(ErrorCodes.ERROR_COMMON, draftDataList, "草稿状态不能添加物流！！");
        }*/

        //根据要保存的订单号查询出来的要保存的所有子单数据
        List<OrdSubOrder> waybillNoSubOrderList = subOrderService.findByOrderNos(new ArrayList<>(orderNoSet));
        //批量订单号
        List<String> waybillNoListForLog = new ArrayList<>();
        waybillNoListForLog.addAll(orderNoSet);
        List<OrdOrder> orderListForLog = Lists.newArrayList();
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(waybillNoListForLog)) {
            orderListForLog = orderService.findByOrderNos(waybillNoListForLog);

        }
        //批量订单的子单
        List<OrdSubOrder> waybillNoSubOrderListForLog = waybillNoSubOrderList;

        //批量子单
        List<OrdSubOrder> subOrderListForLog = subOrderList;
        /**
         *  获取到批量的订单号， 以及不存在于这些订单号中的 其他子单号。
         *
         * 对于批量给订单增加物流信息的waybillNoSetForLog， 增加物流增加日志数据。 涉及订单状态更改。
         * 对于单个子单的， 增加物流增加日志数据，涉及订单状态更改
         *
         * 批量订单号waybillNoSetForLog   Set<String>
         * 批量订单对应的子单waybillNoSubOrderListForLog  List<OrdSubOrder>
         * 批量子单号subOrderListForLog     List<OrdSubOrder>
         */
        List<OrdSubOrder> subOrderListForLogLater = Lists.newArrayList();
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(subOrderListForLog)) {
            for (OrdSubOrder subOrder :
                    subOrderListForLog) {
                if (org.apache.commons.collections.CollectionUtils.isNotEmpty(waybillNoSubOrderListForLog)) {
                    if (!waybillNoSubOrderListForLog.contains(subOrder)) {
                        subOrderListForLogLater.add(subOrder);
                    }
                } else {
                    subOrderListForLogLater.add(subOrder);
                }
            }
        }

        //批量子单对应的订单
        List<OrdOrder> orderListForSub;
        List<String> waybillNosForSub = Lists.newArrayList();
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(subOrderListForLogLater)) {
            subOrderListForLogLater.forEach(subOrder -> {
                waybillNosForSub.add(subOrder.getOrderNo());
            });

        }

        orderListForSub = orderService.findByOrderNos(waybillNosForSub);
        //将子单的数据与要保存的订单的子单数据组装在一起，就成了要保存的数据了。
        subOrderList.addAll(waybillNoSubOrderList);
        Map<String, OrdSubOrder> subOrderMap = EntityUtils.getStringKeyMapFromBeans(subOrderList, "subOrderNo");
        if (CollectionUtils.isEmpty(subOrderMap)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "没有要处理的数据");
        }
        Map<String, String> orderNoWaybillNoMap = subOrderService.findWaybillNoOrderNoMapBySubOrders(new ArrayList<>(subOrderMap.keySet()));


        //判断code是否有效，并得到对应的物流信息
        OrdOrderStatusCode statusCode = statusCodeService.getByCode(code);
        if (ObjectUtils.isEmpty(statusCode)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "该物流信息不存在");
        }
        Map<String, OrderStatus> processOrderMap = Maps.newHashMap();
        String message = "";
        List<String> paramList = EntityUtils.extractMessageByRegular(statusCode.getMessageTemplate(), CommCodes.ORD_TRACKING_REGEX);
        if (!CollectionUtils.isEmpty(paramList)) {
            message = this.getMessage(param);
        }
        //子单状态更新记录
        List<String> orderStatusProcess = Lists.newArrayList();
        orderNoSet = Sets.newHashSet();
        List<OrdOrderTracking> ordOrderTrackingList = new ArrayList<>();
        for (OrdSubOrder subOrder : subOrderMap.values()) {
            OrdOrderTracking orderTracking = new OrdOrderTracking();
            orderTracking.setOrderNo(subOrder.getOrderNo());
            orderTracking.setWaybillNo(orderNoWaybillNoMap.get(orderTracking.getOrderNo()));
            orderTracking.setSubOrderNo(subOrder.getSubOrderNo());
            orderTracking.setTrackMessage(message);
            orderTracking.setServiceOrderNo(null);
            orderTracking.setServiceUid(null);
            orderTracking.setCode(code);
            orderTracking.setOriginalId(null);
            orderTracking.setStatus(CommCodes.TRACKING_STATUS_FINISH);
            orderTracking.setSupplierId(null);
            orderTracking.setType(CommCodes.TRACKING_TYPE_SUPPER);
            orderTracking.setMessageTime(messageTime);
            ordOrderTrackingList.add(orderTracking);

            if (!ObjectUtils.isEmpty(statusCode.getOrderStatus()) && statusCode.getOrderStatus().compareTo(subOrder.getOrderStatus()) > 0) {
                orderStatusProcess.add(subOrder.getSubOrderNo());//子订单要更新状态
                orderNoSet.add(subOrder.getOrderNo());//主订单表要更新状态
            }
        }
        this.batchSave(ordOrderTrackingList);

        if (!CollectionUtils.isEmpty(orderStatusProcess) && !CollectionUtils.isEmpty(orderNoSet)) {
            //更新子订单的状态
            subOrderService.updateOrderStatus(orderStatusProcess, statusCode.getOrderStatus());
            //
            subOrderList = subOrderService.getMinStatusByOrderNos(new ArrayList<>(orderNoSet));
            subOrderMap = EntityUtils.getStringKeyMapFromBeans(subOrderList, "orderNo");
            List<OrdOrder> ordOrderList = orderService.findByOrderNos(new ArrayList<>(orderNoSet));

            for (OrdOrder order : ordOrderList) {
                OrdSubOrder subOrder = subOrderMap.get(order.getOrderNo());
                if (!ObjectUtils.isEmpty(subOrder)) {
                    if (order.getOrderStatus().compareTo(subOrder.getOrderStatus()) < 0) {
                        processOrderMap.put(subOrder.getOrderNo(), subOrder.getOrderStatus());
                    }
                }
            }
            orderService.updateOrderStatus(processOrderMap);
        }
        //更新物流信息，一部分是订单号waybillNoSet-->订单号对应的所有子单waybillNoSubOrderList，一部分子单号subOrderNoSet。
        //subOrderList 是所有的子单数据.    subOrderMap 所有的子单数据。 key->value  key是子单号， value是子单
        // orderNoSet 主单状态更新记录，orderStatusProcess 子单状态更新记录

        //  批量订单号 waybillNoSetForLog   Set<String>
        //批量子单号subOrderListForLogLater     List<OrdSubOrder>
        //Map<String, OrderStatus> processOrderMap   订单的状态变化  订单号 和订单的状态.
        //
        //物流信息
        Integer accountId = PrincipalUtils.getAccountId();
        Integer domainId = PrincipalUtils.getDomainId();
        String trackMessage = getTrackingString(statusCode.getMessageTemplate(), message);
        operationLogService.batchSaveLogisInfoForUpdateLog(orderListForLog, subOrderListForLogLater, orderListForSub, trackMessage, processOrderMap, accountId, domainId);


        return notExitDataList;
    }

    private List<OrdOrder> getNoProcessDataByOrderNo(Set<String> orderNoSet, List<String> notExitDataList, List<String> draftDataList) {
        Set<String> originalOrderNo = Sets.newHashSet();
        originalOrderNo.addAll(orderNoSet);
        //获取前端传递的子订单中的不存在数据和为草稿状态的数据
        List<OrdOrder> orderList = orderService.findByOrderNos(new ArrayList<>(orderNoSet));
        List<String> orderNos = Lists.newArrayList();
        for (OrdOrder ordOrder : orderList) {
            orderNos.add(ordOrder.getOrderNo());
            if (!ObjectUtils.isEmpty(ordOrder.getOrderStatus()) && OrderStatus.DRAFT.equals(ordOrder.getOrderStatus())) {
                draftDataList.add(ordOrder.getOrderNo());
            }
        }
        orderNoSet.removeAll(orderNos);
        notExitDataList.addAll(orderNoSet);
        orderNoSet.addAll(originalOrderNo);
        orderNoSet.removeAll(notExitDataList);
        orderNoSet.removeAll(draftDataList);
        return orderList;
    }

    private List<OrdSubOrder> getNoProcessDataBySubOrderNo(Set<String> subOrderNoSet, List<String> notExitDataList, List<String> draftDataList) {
        List<String> subOrderNos = Lists.newArrayList();
        List<String> orderNos = Lists.newArrayList();

        List<OrdSubOrder> subOrderList = subOrderService.findBySubOrderNos(new ArrayList<>(subOrderNoSet));
        for (OrdSubOrder subOrder : subOrderList) {
            subOrderNos.add(subOrder.getSubOrderNo());
            orderNos.add(subOrder.getOrderNo());
        }
        subOrderNoSet.forEach(subOrderNo -> {
            if (!subOrderNos.contains(subOrderNo)) {
                notExitDataList.add(subOrderNo);
            }
        });

        List<OrdOrder> orderList = orderService.findByOrderNos(orderNos);

        orderList.forEach(order -> {
            if (!ObjectUtils.isEmpty(order.getOrderStatus()) && OrderStatus.DRAFT.equals(order.getOrderStatus())) {
                subOrderList.forEach(subOrder -> {
                    if (order.getWaybillNo().equals(subOrder.getOrderNo())) {
                        draftDataList.add(subOrder.getSubOrderNo());
                    }
                });
            }
        });
        subOrderNoSet.removeAll(notExitDataList);
        subOrderNoSet.removeAll(draftDataList);
        return subOrderList;
    }

    private List processWaybillNos(List<String> contentList, Set<String> orderNoSet, Set<String> subOrderNoSet, int type) {
        List noExistNo = new ArrayList();
        if (OrderTrackingConstants.TrackingAddNoType.TRACKING_ADD_ORDER_NO_TYPE == type) {
            List<OrdOrder> ordOrderList = orderService.findByWaybillNos(contentList);
            if (!CollectionUtils.isEmpty(ordOrderList)) {
                ordOrderList.forEach(ordOrder -> {
                    orderNoSet.add(ordOrder.getWaybillNo());
                });
                contentList.removeAll(orderNoSet);
                noExistNo = contentList;

            }
        } else if ((OrderTrackingConstants.TrackingAddNoType.TRACKING_ADD_SUB_ORDER_NO_TYPE == type)) {
            List<OrdSubOrder> subOrderList = subOrderService.findBySubOrderNos(contentList);
            if (!CollectionUtils.isEmpty(subOrderList)) {
                subOrderList.forEach(subOrder -> subOrderNoSet.add(subOrder.getSubOrderNo()));
            }
            contentList.removeAll(subOrderNoSet);
            noExistNo = contentList;
        }


        List<String> orderNoList = orderService.findOrderNosByWaybillNos(new ArrayList<>(orderNoSet));
        orderNoSet.clear();
        orderNoSet.addAll(orderNoList);
        return noExistNo;

    }


    private String getMessage(List<String> params) {
        String message = null;
        if (!CollectionUtils.isEmpty(params)) {
            StringBuilder trackMessage = new StringBuilder();

            for (String str : params) {
                trackMessage.append(str).append("|");
            }
            message = trackMessage.substring(0, trackMessage.lastIndexOf("|"));
        }
        return message;
    }

    @Override
    public void checkLegal(int type, String param) {
        if (type <= 0 || !StringUtils.hasLength(param)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "参数异常");
        }
        int count = 0;
        switch (type) {
            case CommCodes.ORD_TRACKING_SEARCH_TYPE_WAYBILLNO://根据waybillNo
                count = subOrderService.checkSubOrOrderNo(CommCodes.ORD_TRACKING_SEARCH_TYPE_WAYBILLNO, param);
                break;
            case CommCodes.ORD_TRACKING_SEARCH_TYPE_SUBWAYBILLNO://根据subOrderNo
                count = subOrderService.checkSubOrOrderNo(CommCodes.ORD_TRACKING_SEARCH_TYPE_SUBWAYBILLNO, param);
                break;
            default:
                break;
        }
        if (count <= 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "数据不存在");
        }
    }

    //批量给子单增加对应code的物流信息
    @Override
    public void batchSaveByStatusCode(OrdOrder ordOrder, List<String> subOrderNos, List<OrdOrderStatusCode> statusCodes, Date messageTime) {
        List<OrdOrderTracking> trackingList = Lists.newArrayList();
        if (null != subOrderNos && !subOrderNos.isEmpty() && null != statusCodes && !statusCodes.isEmpty()) {
            subOrderNos.forEach(subOrderNo -> {
                statusCodes.forEach(code -> {
                    OrdOrderTracking tracking = new OrdOrderTracking();
                    tracking.setWaybillNo(ordOrder.getWaybillNo());
                    tracking.setSubOrderNo(subOrderNo);
                    tracking.setOriginalId(0);
                    tracking.setCode(code.getCode());
                    tracking.setType(CommCodes.TRACKING_TYPE_SYSTEM_AUTO);
                    tracking.setStatus(CommCodes.TRACKING_STATUS_FINISH);
                    tracking.setMessageTime(messageTime);
                    trackingList.add(tracking);
                });
            });

        }
        if (!trackingList.isEmpty()) {
            this.batchSave(trackingList);
        }

    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    @Override
    public void batchSaveByStatusCodeTrans(OrdOrder ordOrder, List<String> subOrderNos, List<OrdOrderStatusCode> statusCodes, Date messageTime) {
        this.batchSaveByStatusCode(ordOrder, subOrderNos, statusCodes, messageTime);
    }
}




